/*
 * Shared Memory. Now it's very simple, each shared
 * memory is only a page, and each process can only
 * have one piece.
 */


#include <type.h>
#include "process.h"
#include "mm.h"

struct shared_mem {
	int	shmid;
	int	cpid;	/* create pid */
	int	nat;	/* number of attch */
	u32_t	phy;	/* physical page */
};

/* We don't have kmalloc now, so... */
#define NUM_SHM 10
struct shared_mem Shared_mems[NUM_SHM];

#define SHM_IDLE -1

void init_shm(void)
{
	int i;
	for(i = 0; i < NUM_SHM; i++)
		Shared_mems[i].shmid = SHM_IDLE;
}

int shm_create(void)
{
	int i;

	/* Disable process switch to avoid race condition. */
	disable_sched();

	for(i = 0; i < NUM_SHM; i++) {
		if(Shared_mems[i].shmid == SHM_IDLE)
			break;
	}
	if(i == NUM_SHM)
		;/* TODO: process wait list */
	enable_sched();

	Shared_mems[i].shmid = i;
	Shared_mems[i].cpid = current->pid;
	Shared_mems[i].nat = 0;
	Shared_mems[i].phy = 0;

	return i;
}

/* We just remove the shm struce, but not physical page. */
int shm_remove(int shmid)
{
	if(shmid >= NUM_SHM || Shared_mems[shmid].shmid == SHM_IDLE)
		return -1;

	Shared_mems[shmid].shmid = SHM_IDLE;
	return 0;
}

#define PROC_SHM_ADDR 0xB0000000
void *shm_attach(int shmid)
{
	if(shmid >= NUM_SHM || Shared_mems[shmid].shmid == SHM_IDLE)
		return -1;

	if(Shared_mems[shmid].phy == 0) /* First time. */
		Shared_mems[shmid].phy = new_page(1);
	else
		increase_page(Shared_mems[shmid].phy);

	set_page_table(PROC_SHM_ADDR, Shared_mems[shmid].phy);
	Shared_mems[shmid].nat++;
	return PROC_SHM_ADDR;
}

int shm_detach(int shmid)
{
	if(shmid >= NUM_SHM || Shared_mems[shmid].shmid == SHM_IDLE)
		return -1;

	/* TODO: We should clear PTE for PROC_SHM_ADDR, and
	 * delete the physical page. Since we don't clear PTE
	 * now, cancel the page delete, which will be deleted
	 * when process exits. */
	//delete_page(Shared_mems[shmid].phy);

	Shared_mems[shmid].nat--;
	return 0;
}
